package com.bank.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bank.dto.Result;
import com.bank.entity.DepositType;
import com.bank.exception.BankException;
import com.bank.mapper.DepositTypeMapper;
import com.bank.service.DepositTypeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 存款类型服务实现类
 * 实现存款类型相关的业务逻辑处理
 * 
 * @author 开发团队
 * @version 1.0.0
 * @since 2025-06-19
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class DepositTypeServiceImpl implements DepositTypeService {

    @Autowired
    private DepositTypeMapper depositTypeMapper;

    @Override
    public Result<DepositType> addDepositType(DepositType depositType) {
        log.info("开始新增存款类型：{}", depositType);
        
        try {
            // 验证存款类型信息
            Result<Void> validateResult = validateDepositTypeInfo(depositType);
            if (!validateResult.isSuccess()) {
                return Result.error(validateResult.getMessage());
            }

            // 检查存款名称是否已存在
            Result<Boolean> nameExistsResult = checkSavingNameExists(depositType.getSavingName(), null);
            if (nameExistsResult.getData()) {
                return Result.error("存款名称已存在，请检查后重试");
            }

            // 插入存款类型信息
            int result = depositTypeMapper.insert(depositType);
            if (result > 0) {
                log.info("存款类型新增成功，存款类型ID：{}", depositType.getSavingId());
                return Result.success("存款类型新增成功", depositType);
            } else {
                return Result.error("存款类型新增失败");
            }
        } catch (Exception e) {
            log.error("新增存款类型异常：", e);
            throw new BankException("新增存款类型失败：" + e.getMessage());
        }
    }

    @Override
    public Result<String> deleteDepositType(Integer savingId) {
        log.info("开始删除存款类型，存款类型ID：{}", savingId);
        
        try {
            if (savingId == null) {
                return Result.badRequest("存款类型ID不能为空");
            }

            // 检查存款类型是否存在
            DepositType depositType = depositTypeMapper.selectById(savingId);
            if (depositType == null) {
                return Result.notFound("存款类型不存在");
            }

            // 检查是否有关联的银行卡
            int cardCount = depositTypeMapper.countCardsBySavingId(savingId);
            if (cardCount > 0) {
                return Result.error("该存款类型还有关联的银行卡，无法删除");
            }

            // 删除存款类型
            int result = depositTypeMapper.deleteById(savingId);
            if (result > 0) {
                log.info("存款类型删除成功，存款类型ID：{}", savingId);
                return Result.success("存款类型删除成功");
            } else {
                return Result.error("存款类型删除失败");
            }
        } catch (Exception e) {
            log.error("删除存款类型异常：", e);
            throw new BankException("删除存款类型失败：" + e.getMessage());
        }
    }

    @Override
    public Result<String> batchDeleteDepositTypes(List<Integer> savingIds) {
        log.info("开始批量删除存款类型，存款类型ID列表：{}", savingIds);
        
        try {
            if (savingIds == null || savingIds.isEmpty()) {
                return Result.badRequest("存款类型ID列表不能为空");
            }

            // 检查每个存款类型是否有关联的银行卡
            for (Integer savingId : savingIds) {
                int cardCount = depositTypeMapper.countCardsBySavingId(savingId);
                if (cardCount > 0) {
                    DepositType depositType = depositTypeMapper.selectById(savingId);
                    String savingName = depositType != null ? depositType.getSavingName() : "未知";
                    return Result.error("存款类型【" + savingName + "】还有关联的银行卡，无法删除");
                }
            }

            // 批量删除存款类型
            int result = depositTypeMapper.batchDeleteByIds(savingIds);
            if (result > 0) {
                log.info("批量删除存款类型成功，删除数量：{}", result);
                return Result.success("批量删除存款类型成功，删除数量：" + result);
            } else {
                return Result.error("批量删除存款类型失败");
            }
        } catch (Exception e) {
            log.error("批量删除存款类型异常：", e);
            throw new BankException("批量删除存款类型失败：" + e.getMessage());
        }
    }

    @Override
    public Result<DepositType> updateDepositType(DepositType depositType) {
        log.info("开始修改存款类型：{}", depositType);
        
        try {
            if (depositType.getSavingId() == null) {
                return Result.badRequest("存款类型ID不能为空");
            }

            // 检查存款类型是否存在
            DepositType existingDepositType = depositTypeMapper.selectById(depositType.getSavingId());
            if (existingDepositType == null) {
                return Result.notFound("存款类型不存在");
            }

            // 验证存款类型信息
            Result<Void> validateResult = validateDepositTypeInfo(depositType);
            if (!validateResult.isSuccess()) {
                return Result.error(validateResult.getMessage());
            }

            // 检查存款名称是否已存在（排除当前存款类型）
            Result<Boolean> nameExistsResult = checkSavingNameExists(depositType.getSavingName(), depositType.getSavingId());
            if (nameExistsResult.getData()) {
                return Result.error("存款名称已存在，请检查后重试");
            }

            // 更新存款类型信息
            int result = depositTypeMapper.updateById(depositType);
            if (result > 0) {
                log.info("存款类型修改成功，存款类型ID：{}", depositType.getSavingId());
                return Result.success("存款类型修改成功", depositType);
            } else {
                return Result.error("存款类型修改失败");
            }
        } catch (Exception e) {
            log.error("修改存款类型异常：", e);
            throw new BankException("修改存款类型失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<DepositType> getDepositTypeById(Integer savingId) {
        try {
            if (savingId == null) {
                return Result.badRequest("存款类型ID不能为空");
            }

            DepositType depositType = depositTypeMapper.selectById(savingId);
            if (depositType == null) {
                return Result.notFound("存款类型不存在");
            }

            return Result.success(depositType);
        } catch (Exception e) {
            log.error("查询存款类型异常：", e);
            throw new BankException("查询存款类型失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<DepositType> getDepositTypeBySavingName(String savingName) {
        try {
            if (StringUtils.isBlank(savingName)) {
                return Result.badRequest("存款名称不能为空");
            }

            DepositType depositType = depositTypeMapper.selectBySavingName(savingName);
            if (depositType == null) {
                return Result.notFound("存款类型不存在");
            }

            return Result.success(depositType);
        } catch (Exception e) {
            log.error("根据存款名称查询存款类型异常：", e);
            throw new BankException("查询存款类型失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<DepositType>> getDepositTypesBySavingNameLike(String savingName) {
        try {
            if (StringUtils.isBlank(savingName)) {
                return Result.badRequest("存款名称不能为空");
            }

            List<DepositType> depositTypeList = depositTypeMapper.selectBySavingNameLike(savingName);
            return Result.success(depositTypeList);
        } catch (Exception e) {
            log.error("根据存款名称模糊查询异常：", e);
            throw new BankException("查询存款类型失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<DepositType>> getDepositTypesByCreateTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            if (startTime == null || endTime == null) {
                return Result.badRequest("开始时间和结束时间不能为空");
            }

            if (startTime.isAfter(endTime)) {
                return Result.badRequest("开始时间不能晚于结束时间");
            }

            List<DepositType> depositTypeList = depositTypeMapper.selectByCreateTimeRange(startTime, endTime);
            return Result.success(depositTypeList);
        } catch (Exception e) {
            log.error("根据创建时间范围查询异常：", e);
            throw new BankException("查询存款类型失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<IPage<DepositType>> getDepositTypesPage(Page<DepositType> page, String savingName, String description,
                                                         LocalDateTime startTime, LocalDateTime endTime) {
        try {
            if (startTime != null && endTime != null && startTime.isAfter(endTime)) {
                return Result.badRequest("开始时间不能晚于结束时间");
            }

            IPage<DepositType> result = depositTypeMapper.selectPageWithConditions(page, savingName, description, startTime, endTime);
            return Result.success(result);
        } catch (Exception e) {
            log.error("分页查询存款类型异常：", e);
            throw new BankException("查询存款类型失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<DepositType>> getAllAvailableDepositTypes() {
        try {
            List<DepositType> depositTypeList = depositTypeMapper.selectAllAvailable();
            return Result.success(depositTypeList);
        } catch (Exception e) {
            log.error("查询所有可用存款类型异常：", e);
            throw new BankException("查询存款类型失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<Boolean> checkSavingNameExists(String savingName, Integer excludeSavingId) {
        try {
            if (StringUtils.isBlank(savingName)) {
                return Result.badRequest("存款名称不能为空");
            }

            int count = depositTypeMapper.countBySavingName(savingName, excludeSavingId);
            return Result.success(count > 0);
        } catch (Exception e) {
            log.error("检查存款名称是否存在异常：", e);
            throw new BankException("检查存款名称失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<Integer> getDepositTypeCount() {
        try {
            int count = depositTypeMapper.selectTotalCount();
            return Result.success(count);
        } catch (Exception e) {
            log.error("获取存款类型统计信息异常：", e);
            throw new BankException("获取存款类型统计信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<String> exportDepositTypesToCSV() {
        try {
            List<DepositType> depositTypeList = depositTypeMapper.selectList(null);
            
            StringWriter stringWriter = new StringWriter();
            CSVFormat csvFormat = CSVFormat.DEFAULT.withHeader(
                "存款编号", "存款名称", "存款描述", "创建时间"
            );
            
            try (CSVPrinter csvPrinter = new CSVPrinter(stringWriter, csvFormat)) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                
                for (DepositType depositType : depositTypeList) {
                    csvPrinter.printRecord(
                        depositType.getSavingId(),
                        depositType.getSavingName(),
                        depositType.getDescription(),
                        depositType.getCreateTime() != null ? depositType.getCreateTime().format(formatter) : ""
                    );
                }
            }
            
            log.info("存款类型导出成功，导出数量：{}", depositTypeList.size());
            return Result.success("存款类型导出成功", stringWriter.toString());
        } catch (IOException e) {
            log.error("导出存款类型到CSV异常：", e);
            throw new BankException("导出存款类型失败：" + e.getMessage());
        }
    }

    @Override
    public Result<Void> validateDepositTypeInfo(DepositType depositType) {
        if (depositType == null) {
            return Result.badRequest("存款类型信息不能为空");
        }

        if (StringUtils.isBlank(depositType.getSavingName())) {
            return Result.badRequest("存款名称不能为空");
        }

        if (depositType.getSavingName().length() > 50) {
            return Result.badRequest("存款名称长度不能超过50个字符");
        }

        if (StringUtils.isNotBlank(depositType.getDescription()) && depositType.getDescription().length() > 200) {
            return Result.badRequest("存款描述长度不能超过200个字符");
        }

        return Result.success();
    }
}
